import argparse
import logging
import os
import os.path
import sys
from hashlib import md5

import pyftpdlib.handlers
from pyftpdlib.authorizers import AuthenticationFailed, DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import MultiprocessFTPServer

FTP_ROOT = '/ftp_root'

pyftpdlib.handlers.PassiveDTP.timeout = None


class DummyMD5Authorizer(DummyAuthorizer):

    def validate_authentication(self, username, password, handler):
        if sys.version_info >= (3, 0):
            password = md5(password.encode('latin1'))
        hash = md5(password).hexdigest()
        try:
            if self.user_table[username]['pwd'] != hash:
                raise KeyError
        except KeyError:
            raise AuthenticationFailed


def run_ftpd(user, password, host, port, passive, anon):
    user_dir = os.path.join(FTP_ROOT, user)
    if not os.path.isdir(user_dir):
        os.mkdir(user_dir)
    hash = md5(b'{}'.format(password)).hexdigest()
    authorizer = DummyMD5Authorizer()
    authorizer.add_user(user, hash, user_dir, perm='elradfmwMT')
    if anon:
        authorizer.add_anonymous('/ftp_root/nobody')

    handler = FTPHandler
    handler.authorizer = authorizer
    handler.permit_foreign_addresses = True
    passive_ports = map(int, passive.split('-'))
    handler.passive_ports = range(passive_ports[0], passive_ports[1])
    logging.basicConfig(filename='/log/pyftpd.log', level=logging.INFO)

    server = MultiprocessFTPServer((host, port), handler)
    server.max_cons = 256
    server.max_cons_per_ip = 5
    server.serve_forever()


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    parser.add_argument(
        '--user', default='dimabru',
        help='Username for FTP acess (user will be created)')
    parser.add_argument('--password', default='Dimabru001',
                        help='Password for FTP user.')
    parser.add_argument('--host', default='0.0.0.0')
    parser.add_argument('--port', type=int, default=21)
    parser.add_argument('--passive', default='3000-3010',
                        help='Range of passive ports')
    parser.add_argument('--anon', action='store_true',
                        help='Allow anonymous access')
    args = parser.parse_args()
    run_ftpd(**vars(args))


if __name__ == '__main__':
    main()
